package com.qfedu.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qfedu.common.core.entity.LocationRecord;
import com.qfedu.config.AmapConfig;
import com.qfedu.mapper.LocationRecordMapper;
import com.qfedu.service.AmapService;
import com.qfedu.utils.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;

/**
 * 高德地图服务实现类
 * 提供IP定位、地理编码、逆地理编码等核心功能
 */
@Service
public class AmapServiceImpl extends ServiceImpl<LocationRecordMapper, LocationRecord>
        implements AmapService {

    private static final Logger logger = LoggerFactory.getLogger(AmapServiceImpl.class);

    @Autowired
    private AmapConfig amapConfig; // 高德配置参数（key/url等）

    /**
     * 初始化时打印配置信息（调试用）
     */
    @PostConstruct
    public void init() {
        logger.info("高德地图配置加载: key={}, ipUrl={}, geoUrl={}, regeoUrl={}",
                amapConfig.getKey(),
                amapConfig.getIpUrl(),
                amapConfig.getGeocodeUrl(),
                amapConfig.getRegeoUrl());
    }

    // ==================== 核心服务方法 ====================

    /**
     * IP定位服务
     * @param ip 需要查询的IP地址
     * @return 包含定位结果的JSON对象（status=1成功，0失败）
     */
    @Override
    public JSONObject ipLocation(String ip) {
        // 参数校验
        if (!StringUtils.hasText(ip)) {
            return createErrorResponse("IP地址不能为空");
        }

        try {
            // 配置校验
            validateConfig(amapConfig.getKey(), amapConfig.getIpUrl());

            // 构建请求URL（示例：https://restapi.amap.com/v3/ip?key=xxx&ip=8.8.8.8）
            String url = String.format("%s?key=%s&ip=%s",
                    amapConfig.getIpUrl().trim(),
                    amapConfig.getKey().trim(),
                    HttpUtil.encodeUrlParam(ip));

            validateUrl(url); // URL格式校验
            logger.info("请求高德IP定位API: {}", url);

            // 发送HTTP请求并解析响应
            String response = HttpUtil.doGet(url);
            logger.debug("高德IP定位API响应: {}", response);

            return parseResponse(response);
        } catch (Exception e) {
            logger.error("IP定位失败, IP: " + ip, e);
            return createErrorResponse("IP定位失败: " + e.getMessage());
        }
    }

    /**
     * 逆地理编码服务（坐标→地址）
     * @param longitude 经度
     * @param latitude 纬度
     * @return 包含地址信息的JSON响应
     */
    @Override
    public JSONObject regeoLocation(Double longitude, Double latitude) {
        if (longitude == null || latitude == null) {
            return createErrorResponse("经纬度不能为空");
        }

        try {
            validateConfig(amapConfig.getKey(), null); // 仅校验Key

            // 构建请求URL（示例：https://restapi.amap.com/v3/geocode/regeo?key=xxx&location=116.4,39.9）
            String location = longitude + "," + latitude;
            String url = String.format("%s?key=%s&location=%s",
                    amapConfig.getRegeoUrl(),
                    amapConfig.getKey(),
                    HttpUtil.encodeUrlParam(location));

            logger.debug("请求高德逆地理编码API: {}", url);
            String response = HttpUtil.doGet(url);
            logger.debug("高德逆地理编码API响应: {}", response);

            return parseResponse(response);
        } catch (Exception e) {
            logger.error("逆地理编码失败, 位置: " + longitude + "," + latitude, e);
            return createErrorResponse("逆地理编码失败: " + getErrorMessage(e));
        }
    }

    /**
     * 地理编码服务（地址→坐标）
     * @param address 结构化地址（如"北京市海淀区中关村大街1号"）
     * @return 包含经纬度的JSON响应
     */
    @Override
    public JSONObject geoLocation(String address) {
        if (!StringUtils.hasText(address)) {
            return createErrorResponse("地址不能为空");
        }

        try {
            validateConfig(amapConfig.getKey(), null); // 仅校验Key

            // 构建请求URL（示例：https://restapi.amap.com/v3/geocode/geo?key=xxx&address=北京）
            String url = String.format("%s?key=%s&address=%s",
                    amapConfig.getGeocodeUrl(),
                    amapConfig.getKey(),
                    HttpUtil.encodeUrlParam(address));

            logger.debug("请求高德地理编码API: {}", url);
            String response = HttpUtil.doGet(url);
            logger.debug("高德地理编码API响应: {}", response);

            return parseResponse(response);
        } catch (Exception e) {
            logger.error("地理编码失败, 地址: " + address, e);
            return createErrorResponse("地理编码失败: " + getErrorMessage(e));
        }
    }

    /**
     * 保存定位记录到数据库
     * @param record 定位记录实体
     * @return 是否保存成功
     */
    @Override
    public boolean saveLocationRecord(LocationRecord record) {
        try {
            return this.save(record); // 调用MyBatis-Plus的save方法
        } catch (Exception e) {
            logger.error("保存定位记录失败", e);
            return false;
        }
    }

    // ==================== 内部工具方法 ====================

    /**
     * 校验高德配置参数
     * @param key 高德API Key
     * @param url 需要校验的API地址（可选）
     * @throws IllegalStateException 当配置不合法时抛出
     */
    private void validateConfig(String key, String url) {
        if (amapConfig == null || !StringUtils.hasText(key)) {
            throw new IllegalStateException("高德地图配置未正确初始化");
        }
        if (url != null && !StringUtils.hasText(url)) {
            throw new IllegalStateException("高德API地址未配置");
        }
    }

    /**
     * 校验URL合法性
     * @param url 待校验的URL
     * @throws IllegalArgumentException 当URL非法时抛出
     */
    private void validateUrl(String url) {
        if (!url.startsWith("http")) {
            throw new IllegalArgumentException("无效的API URL: " + url);
        }
    }

    /**
     * 解析高德API响应
     * @param response 原始JSON字符串
     * @return 解析后的JSONObject
     */
    private JSONObject parseResponse(String response) {
        if (!StringUtils.hasText(response)) {
            return createErrorResponse("空响应");
        }
        try {
            JSONObject result = JSON.parseObject(response);
            return result != null ? result : createErrorResponse("响应解析失败");
        } catch (Exception e) {
            logger.error("解析高德API响应失败", e);
            return createErrorResponse("响应解析失败: " + e.getMessage());
        }
    }

    /**
     * 创建错误响应
     * @param message 错误信息
     * @return 标准化错误JSON（status=0）
     */
    private JSONObject createErrorResponse(String message) {
        JSONObject result = new JSONObject();
        result.put("status", "0"); // 高德标准错误码
        result.put("info", message);
        return result;
    }

    /**
     * 提取异常信息（避免null）
     */
    private String getErrorMessage(Exception e) {
        return e.getMessage() != null ? e.getMessage() : "未知错误";
    }
}